use std::path::Path;
use std::fs;
use std::io::{self, BufRead, BufReader};
use std::process::{Command, Stdio};
use std::os::windows::process::CommandExt;
use std::thread;
use reqwest;
use zip::ZipArchive;
use tauri::Window;
use crate::config::AppConfig;

pub struct SteamSetup;

impl SteamSetup {
    pub async fn download_and_install_steamcmd(install_path: String, window: Window) -> Result<String, String> {
        let steamcmd_exe = format!("{}\\steamcmd.exe", install_path);
        if Path::new(&steamcmd_exe).exists() {
            // SteamCMD 已存在，跳过下载
        } else {
            Self::download_steamcmd(&install_path, &window).await?;
        }
        
        // 运行 steamcmd.exe 进行初始安装
        let _ = window.emit("steamcmd-log", "正在启动 SteamCMD 进行初始安装...");
        
        let window_clone = window.clone();
        let install_path_clone = install_path.clone();
        thread::spawn(move || {
            Self::run_steamcmd_initial_setup(&install_path_clone, &window_clone);
        });
        
        Ok("SCUM安装|更新 完成".to_string())
    }

    async fn download_steamcmd(install_path: &str, window: &Window) -> Result<(), String> {
        let steamcmd_url = "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip";
        let zip_path = format!("{}\\steamcmd.zip", install_path);
        
        // 创建安装目录
        if !Path::new(install_path).exists() {
            fs::create_dir_all(install_path).map_err(|e| format!("创建目录失败: {}", e))?;
        }
        
        // 发送日志到前端
        let _ = window.emit("steamcmd-log", "正在检查网络连接...");
        let _ = window.emit("steamcmd-log", "连接到 Steam 服务器...");
        let _ = window.emit("steamcmd-log", "开始下载 SteamCMD...");
        
        // 下载文件
        let client = reqwest::Client::new();
        let response = client.get(steamcmd_url)
            .send()
            .await
            .map_err(|e| format!("下载失败: {}", e))?;
        
        if !response.status().is_success() {
            return Err(format!("HTTP错误: {}", response.status()));
        }
        
        let bytes = response.bytes().await
            .map_err(|e| format!("读取响应失败: {}", e))?;
        
        let _ = window.emit("steamcmd-log", "下载进度: 100%");
        
        // 保存 ZIP 文件
        let _ = window.emit("steamcmd-log", "正在保存文件...");
        fs::write(&zip_path, &bytes)
            .map_err(|e| format!("保存文件失败: {}", e))?;
        
        // 解压文件
        Self::extract_zip_file(&zip_path, install_path, window)?;
        
        // 删除 ZIP 文件
        let _ = window.emit("steamcmd-log", "正在清理临时文件...");
        fs::remove_file(&zip_path)
            .map_err(|e| format!("删除ZIP文件失败: {}", e))?;
        
        let _ = window.emit("steamcmd-log", "验证安装完整性...");
        
        // 验证关键文件是否存在
        let steamcmd_exe = format!("{}\\steamcmd.exe", install_path);
        if !Path::new(&steamcmd_exe).exists() {
            return Err("SteamCMD 安装不完整，steamcmd.exe 文件缺失".to_string());
        }
        
        let _ = window.emit("steamcmd-log", "SteamCMD 安装完成！");
        Ok(())
    }

    fn extract_zip_file(zip_path: &str, install_path: &str, window: &Window) -> Result<(), String> {
        let _ = window.emit("steamcmd-log", "正在解压文件...");
        
        let file = fs::File::open(zip_path)
            .map_err(|e| format!("打开ZIP文件失败: {}", e))?;
        
        let mut archive = ZipArchive::new(file)
            .map_err(|e| format!("读取ZIP文件失败: {}", e))?;
        
        for i in 0..archive.len() {
            let mut file = archive.by_index(i)
                .map_err(|e| format!("读取ZIP条目失败: {}", e))?;
            
            let outpath = Path::new(install_path).join(file.name());
            
            if file.name().ends_with('/') {
                fs::create_dir_all(&outpath)
                    .map_err(|e| format!("创建目录失败: {}", e))?;
            } else {
                if let Some(p) = outpath.parent() {
                    if !p.exists() {
                        fs::create_dir_all(p)
                            .map_err(|e| format!("创建父目录失败: {}", e))?;
                    }
                }
                
                let mut outfile = fs::File::create(&outpath)
                    .map_err(|e| format!("创建文件失败: {}", e))?;
                io::copy(&mut file, &mut outfile)
                    .map_err(|e| format!("写入文件失败: {}", e))?;
            }
        }
        
        Ok(())
    }

    fn run_steamcmd_initial_setup(install_path: &str, window: &Window) {
        let steamcmd_path = format!("{}\\steamcmd.exe", install_path);
        
        // 运行 steamcmd.exe 进行初始安装，使用 +quit 参数让它自动退出
        let mut child = match Command::new(&steamcmd_path)
            .current_dir(install_path)
            .args(&["+quit"])
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .creation_flags(0x08000000) // CREATE_NO_WINDOW
            .spawn() {
                Ok(child) => child,
                Err(e) => {
                    let _ = window.emit("steamcmd-log", &format!("启动 SteamCMD 失败: {}", e));
                    return;
                }
            };
        
        let _ = window.emit("steamcmd-log", "SteamCMD 已启动，正在进行安装|更新...");
        
        // 处理输出
        Self::handle_process_output(&mut child, window, "SteamCMD".to_string());
        
        // 等待 SteamCMD 初始安装完成
        match child.wait() {
            Ok(status) => {
                let _ = window.emit("steamcmd-log", &format!("SteamCMD 安装|更新 完成，退出码: {}", status));
                // 开始安装 SCUM 服务器
                Self::install_scum_server(install_path, window);
            }
            Err(e) => {
                let _ = window.emit("steamcmd-log", &format!("等待 SteamCMD 安装|更新 进程失败: {}", e));
            }
        }
    }

    fn install_scum_server(install_path: &str, window: &Window) {
        let _ = window.emit("steamcmd-log", "开始安装|更新 SCUM 服务器...");
        
        let steamcmd_path = format!("{}\\steamcmd.exe", install_path);
        
        // 运行 SCUM 安装命令
        let mut scum_child = match Command::new(&steamcmd_path)
            .current_dir(install_path)
            .args(&["+login", "anonymous", "+app_update", "3792580", "validate", "+quit"])
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .creation_flags(0x08000000) // CREATE_NO_WINDOW
            .spawn() {
                Ok(child) => child,
                Err(e) => {
                    let _ = window.emit("steamcmd-log", &format!("启动 SCUM 安装|更新 失败: {}", e));
                    return;
                }
            };
        
        // 处理输出
        Self::handle_process_output(&mut scum_child, window, "SCUM 安装|更新".to_string());
        
        // 等待 SCUM 安装完成
        let window_clone = window.clone();
        let install_path_clone = install_path.to_string();
        thread::spawn(move || {
            match scum_child.wait() {
                Ok(status) => {
                    let _ = window_clone.emit("steamcmd-log", &format!("SCUM 安装|更新 进程结束，退出码: {}", status));
                    if status.success() {
                        let _ = window_clone.emit("steamcmd-log", "SCUM 服务器安装|更新 成功！");
                        let _ = window_clone.emit("scum-install-finished", "success");
                        
                        // 标记安装完成，保存所有路径信息
                        let _ = window_clone.emit("mark-installation-complete", &install_path_clone);
                        
                        // 直接保存配置到文件
                        if let Ok(mut config) = AppConfig::load() {
                            if let Err(e) = config.update_install_path(install_path_clone.clone(), true) {
                                let _ = window_clone.emit("steamcmd-log", &format!("保存配置失败: {}", e));
                            } else {
                                let _ = window_clone.emit("steamcmd-log", "配置已保存到 ac-god-panel-config.json");
                            }
                        }
                    } else {
                        let _ = window_clone.emit("steamcmd-log", "SCUM 服务器安装|更新 失败！");
                    }
                }
                Err(e) => {
                    let _ = window_clone.emit("steamcmd-log", &format!("等待 SCUM 安装|更新 进程失败: {}", e));
                }
            }
        });
    }

    fn handle_process_output(child: &mut std::process::Child, window: &Window, prefix: String) {
        let stdout = child.stdout.take().unwrap();
        let stderr = child.stderr.take().unwrap();
        let (tx, rx) = std::sync::mpsc::channel();
        
        // 处理 stdout
        {
            let tx = tx.clone();
            let prefix = prefix.clone();
            thread::spawn(move || {
                let reader = BufReader::new(stdout);
                for line in reader.lines() {
                    if let Ok(line) = line {
                        tx.send((prefix.clone(), line)).ok();
                    }
                }
            });
        }
        
        // 处理 stderr
        {
            let tx = tx.clone();
            let prefix = format!("{} 错误", prefix);
            thread::spawn(move || {
                let reader = BufReader::new(stderr);
                for line in reader.lines() {
                    if let Ok(line) = line {
                        tx.send((prefix.clone(), line)).ok();
                    }
                }
            });
        }
        
        // 统一接收并 emit
        let window_clone = window.clone();
        thread::spawn(move || {
            while let Ok((prefix, line)) = rx.recv() {
                let _ = window_clone.emit("steamcmd-log", &format!("{}: {}", prefix, line));
            }
            let _ = window_clone.emit("steamcmd-log", &format!("{} 输出读取完成", prefix));
        });
    }
} 